﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace FinMkts
{
    /// <summary>
    /// A contract between two parties stipulating that the seller will pay to the buyer the difference 
    /// between the current value of an asset and its value at contract time.
    /// </summary>
    /// <remarks>
    /// what is unique? how to calculate Open Trade Equity?  
    /// The fact this is levaged and therefore interest and commission is charged?
    /// </remarks>
    public class ContractForDifference 
        : FinancialInstrument, ILeveragedInstrument
    {
        public virtual Guid BaseInstrumentId { get; set; }

        public virtual FinancialInstrument BaseInstrument { get; set; }

        ///// <summary>
        ///// Check the CFD is correctly set up in all market listings
        ///// </summary>
        //public void Invariant()
        //{
        //    CheckCommissionFeeExists();
        //    CheckFinancingFeeExists();
        //}

        ///// <summary>
        ///// Make sure this CFD is charing commission or the spread is being widened
        ///// </summary>
        //private void CheckCommissionFeeExists()
        //{
        //    var noCommission = from listing in MarketListings
        //                       where !listing.Fees.Any(fee => fee is Commission || fee is SpreadWidening)
        //                       select string.Format("{0} ({1})", listing.MarketPlace.Name, listing.ListingCode);

        //    if (noCommission.Any())
        //    {
        //        var message = string.Format("CFD '{0}' is not being charged commission or the spread being widened in the following markets: {1}",
        //                                    Name, string.Join(", ", noCommission.ToArray()));
        //        throw new InvalidOperationException(message);
        //    }
        //}

        ///// <summary>
        ///// Make sure this CFD is charging overnight financing
        ///// </summary>
        //private void CheckFinancingFeeExists()
        //{
        //    var noFinancing = from listing in MarketListings
        //                      where !listing.Fees.Any(fee => fee is OvernightFinancing)
        //                      select string.Format("{0} ({1})", listing.MarketPlace.Name, listing.ListingCode);

        //    if (noFinancing.Any())
        //    {
        //        var message = string.Format("CFD '{0}' is not being charged financing in the following markets: {1}",
        //                                    Name, string.Join(", ", noFinancing.ToArray()));
        //        throw new InvalidOperationException(message);
        //    }
        //}

        /// <summary>
        /// Calculate the margin on a <see cref="Position"/>.
        /// </summary>
        /// <param name="position"></param>
        /// <returns>The margin of the <paramref name="position"/> in the <see cref="Currency"/> of the <see cref="FinancialInstrument"/></returns>
        public decimal CalculateMargin(Position position)
        {
            throw new NotImplementedException();
        }

        public override bool CanGetUnderliners
        {
            get { return true; }
        }

        public override string TypeName
        {
            get { return "CFD"; }
        }

        /// <summary>
        /// The things this instrument is based on
        /// </summary>
        public override IEnumerable<FinancialInstrument> GetUnderliners()
        {
            return new [] {BaseInstrument}; 
        }
    }
}
